package org.ws.task.model;

import com.google.common.collect.Maps;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 任务统计
 */
public class TaskStatistics {

    // 任务总数
    private AtomicInteger totalTaskCount;
    // 状态数量
    private Map<TaskStatus,AtomicInteger> taskStatusCountMap;

    private Map<String,AtomicInteger> failedTaskMap;

    private int failedRetryCount = 3;

    private String name;

    public TaskStatistics(String name){
        init();
        this.name = name;
    }

    public void init(){
        totalTaskCount = new AtomicInteger(0);
        taskStatusCountMap = new ConcurrentHashMap<>();
        failedTaskMap = new ConcurrentHashMap<>();
        TaskStatus[] values = TaskStatus.values();
        for (TaskStatus status : values) {
            taskStatusCountMap.put(status,new AtomicInteger(0));
        }
    }

    /**
     * 总数：只增不减
     * @return 总数
     */
    public int addReadyTask(){
        taskStatusCountMap.get(TaskStatus.READY).incrementAndGet();
        return totalTaskCount.incrementAndGet();
    }

    public int addReadyTask(int size){
        taskStatusCountMap.get(TaskStatus.READY).addAndGet(size);
        return totalTaskCount.addAndGet(size);
    }

    public synchronized void changeStatus(TaskStatus source,TaskStatus target){
        taskStatusCountMap.get(source).decrementAndGet();
        taskStatusCountMap.get(target).incrementAndGet();
    }

    public int total() {
        return totalTaskCount.get();
    }

    public int ready(){
        return getStatusCount(TaskStatus.READY);
    }

    /**
     * 分发
     * @return
     */
    public int distributed(){
        return getStatusCount(TaskStatus.DISTRIBUTED);
    }

    /**
     * 处理中
     * @return
     */
    public int processing(){
        return getStatusCount(TaskStatus.PROCESSING);
    }

    /**
     * 成功
     * @return
     */
    public int success(){
        return getStatusCount(TaskStatus.SUCCESS);
    }

    /**
     * 失败
     * @return
     */
    public int failure(){
        return getStatusCount(TaskStatus.FAILURE);
    }

    public void doDistributed(){
        changeStatus(TaskStatus.READY,TaskStatus.DISTRIBUTED);
    }

    public void doProcessing(){
        changeStatus(TaskStatus.DISTRIBUTED,TaskStatus.PROCESSING);
    }

    public void doSuccess(){
        changeStatus(TaskStatus.PROCESSING,TaskStatus.SUCCESS);
    }

    public void doFailure(String taskId){
        AtomicInteger atomicInteger = failedTaskMap.getOrDefault(taskId, new AtomicInteger(0));
        atomicInteger.incrementAndGet();
        failedTaskMap.putIfAbsent(taskId,atomicInteger);
        changeStatus(TaskStatus.PROCESSING,TaskStatus.FAILURE);
    }

    public void doRetry(String taskId){
        // TODO
        AtomicInteger atomicInteger = failedTaskMap.getOrDefault(taskId, new AtomicInteger(0));
        if(atomicInteger.get()<=failedRetryCount) {
            changeStatus(TaskStatus.FAILURE, TaskStatus.DISTRIBUTED);
        }
    }


    private int getStatusCount(TaskStatus status){
        return taskStatusCountMap.get(status).get();
    }

    public Map<String,Object> getData(){
        Map<String,Object> data = Maps.newConcurrentMap();
        TaskStatus[] values = TaskStatus.values();
        data.put("name",name);
        data.put("total",total());
        Map<String,Integer> statusMap = Maps.newConcurrentMap();
        for (TaskStatus status : values) {
            statusMap.put(status.name(),getStatusCount(status));
        }
        data.put("status",statusMap);
        return data;
    }
}
